package Element;
/*
 *  J2Egn version 2.6.28
 *  Author: Van Tan Tai 2010-2011
 *  Virtual-KEY use for inputing text
 */
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

import Core.Event;
import Core.GLives;
import Core.RGBFont;
import Core.Touch;

public class VirtualKEY {
	public static VirtualKEY ins = null;

	private int KEY_WIDTH = 21;
	private int KEY_HEIGHT = 25;
	private final short KEY_DISTANCE = 3;
	private final String sKey[][] ={
			{"1","2","3","4","5","6","7","8","9","0"},
			{"q","w","e","r","t","y","u","i","o","p"},
			{"a","s","d","f","g","h","j","k","l","<"},
			{"!*","z","x","c","v","b","n","m"," ",""}
	};
	private final String sNumFull[][] ={
			{"1","2.abc","3.def", ">>"},
			{"4.ghi","5.jkl","6.mno", "<<"},
			{"7.pqrs","8.tuv","9.wxyz", "C"},
			{"*","0","123", ""}
	};
	private final String sNumLite[][] ={
			{"1","2","3", ">>"},
			{"4","5","6", "<<"},
			{"7","8","9", "C"},
			{"*","0","abc", ""}
	};
	private final String sSbol[][]={
			{"!","?","_","/","&","%","(",")","-","+"},
			{"$",".",",","","","","",";",":","="},
			{"@" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"<"},
			{"Ab","","" ,"" ,"" ,"" ,"" ,"" ,"",""}
	};
	/** 0: QWERTY 1: SPECIAL 2: ABCNUM 3: NUM */
	private byte style = 0;
	private boolean isUpperCase = false;
	private boolean bShow = false;
	private String arrKey[][];
	private int iLeft_Qwerty = 0;
	private int iTop_Qwerty = 43;
	public int w,h, rw,rh;
	private int keyPosX = -1, keyPosY = -1;
	private Image img_buffKeyBoard = null;
	private Graphics gg = null;
	private String sSK[] = new String[3];
	private Image imgSK[] = new Image[3];
	private Event eLSK=null, eRSK=null;
	private int index = -1;
	
	private int trans = 0, hook = 0;
	private boolean isOpening = true, isEffect = false;
	
	public VirtualKEY(){
		ins = this;
	}
	public void setBound(int x, int y, int width, int height, byte imode){
		
		w = width==-1 ? GLives.ScreenWidth : width;
		h = height==-1 ? GLives.ScreenHeight : height;
		
		if(img_buffKeyBoard != null){
			img_buffKeyBoard = null;
			System.gc();
		}
		img_buffKeyBoard= Image.createImage(w + 1, h + 1);
		gg = img_buffKeyBoard.getGraphics();
		
		if(imode > -1) style = imode;
		
		make_BaseKeyBoard();
		
		iLeft_Qwerty = x==-1 ? (GLives.ScreenWidth - rw) >> 1 : x < -1 ? GLives.ScreenWidth - rw + x :  x;
		iTop_Qwerty = y==-1 ? GLives.ScreenHeight - rh : y < -1 ? GLives.ScreenHeight - rh + y : y;
	}
	
	public void setCommand(Event eventLf, Event eventRg){
		eLSK = eventLf; eRSK = eventRg; drawCommand();
		if(eRSK != null || eLSK != null){
			sKey[sKey.length - 1][sKey[0].length - 2] = "_";
		} else sKey[sKey.length - 1][sKey[0].length - 2] = " ";
	}
	public void setCommand(String cmdLeft, String cmdMidle, String cmdRight){
		sSK[0] = cmdLeft; sSK[1] = cmdMidle; sSK[2] = cmdRight; drawCommand();
	}
	public void setCommand(Image imgL, Image imgM, Image imgR){
		imgSK[0]= imgL; imgSK[1]=imgM; imgSK[2]=imgR; drawCommand();
	}
	
	public void showKeyboard(int x, int y, boolean isEffect){
		if(!GLives.isTouchable) return;
		bShow = true;
		iLeft_Qwerty = x==-1 ? (GLives.ScreenWidth - rw) >> 1 : x < -1 ? GLives.ScreenWidth - rw + x :  x;
		iTop_Qwerty = y==-1 ? GLives.ScreenHeight - rh : y < -1 ? GLives.ScreenHeight - rh + y : y;
		
		if(isEffect){
			isOpening = true;
			this.isEffect = isEffect;
			trans = GLives.ScreenHeight - iTop_Qwerty;
		}
	}
	
	public boolean isShow(){
		//System.out.println("isEffect="+isEffect+" isOpening="+isOpening+" bShow="+bShow);
		return isEffect ? isOpening : bShow;
	}
	
	public void hideKeyboard(){
		if(isEffect){
			isOpening = false;
			hook = GLives.ScreenHeight - iTop_Qwerty;
		} else
		bShow = false;
	}
	
	public void update(){
		// effect
		if(isEffect){
			if(isOpening){
				if(trans > 0) trans -= (trans + 2)>>1;
			} else {
				if(trans < hook) trans += (hook - trans + 2)>>1;
				else bShow = false;
			}
		}
	}
	
	public void paint(Graphics g) {
		if(!bShow) return;
		
		update();
		
		// draw base Keyboard
		if(img_buffKeyBoard != null)
			g.drawRegion(img_buffKeyBoard, 0, 0, rw, rh, 0, iLeft_Qwerty, iTop_Qwerty + trans, 0);
		// draw select Key
		if(Touch.isPressed){
			if(keyPosX != -1 && keyPosY != -1)
				draw_Key(g, keyPosY, keyPosX, iLeft_Qwerty, iTop_Qwerty, true);
			else if(index != -1)
				draw_Key(g, index, iLeft_Qwerty, iTop_Qwerty, true);
		}
	}

	/* Pointer Pressed */
	public boolean pointer(int x, int y) {
		index = keyPosX = keyPosY = -1;
		
		if(isClickOut(x, y))
			return false;
		
		if(eRSK != null && y > iTop_Qwerty + (KEY_HEIGHT + KEY_DISTANCE)*4){
			if(x < iLeft_Qwerty + (rw>>2))
				index = 0;
			else if(x < iLeft_Qwerty + (rw>>2) + (rw>>1))
				index = 1;
			else
				index = 2;
			return true;
		}
		
		int col = -1, row = -1;
		col = (x-iLeft_Qwerty)/(KEY_WIDTH + KEY_DISTANCE);
		if(x - iLeft_Qwerty - col*(KEY_WIDTH + KEY_DISTANCE) > KEY_WIDTH) return true;
		row = (y-iTop_Qwerty)/(KEY_HEIGHT + KEY_DISTANCE);
		if(y - iTop_Qwerty - row*(KEY_HEIGHT + KEY_DISTANCE) > KEY_HEIGHT) return true;
		
		//System.out.println("col="+col+" row="+row);
		if(col >= 0 && col < arrKey[0].length && row >= 0 && row < arrKey.length){
			keyPosX = col;
			keyPosY = row;
		}
		return true;
	}
	
	public boolean isClickOut(int x, int y){
		return (x < iLeft_Qwerty || x > iLeft_Qwerty + rw || y < iTop_Qwerty || y > iTop_Qwerty + rh);
	}
	
	/* Pointer Released */
	public void pointer_Released(int x, int y) {
		// KEY return
		if(keyPosX != -1 && keyPosY != -1){
			int code = passKEY(keyPosY, keyPosX);
			if(code != -43){
				boolean bk = TextInput.me.isqwerty;
				TextInput.me.isqwerty = (style < 2);
				GLives.ins.onkeyDown(code);
				TextInput.me.isqwerty = bk;
			}
		} else if(index != -1){
			if(index == 0)
				eLSK.action();
			else if(index == 1)
				GLives.ins.onkeyDown(32);
			else eRSK.action();
		}
		// release key
		index = keyPosX = keyPosY = -1;
	}
	
	private void make_BaseKeyBoard(){
		if(style == 0) arrKey = sKey;
		else if(style == 1) arrKey = sSbol;
		else if(style == 2) arrKey = sNumFull;
		else if(style == 3) arrKey = sNumLite;
		KEY_WIDTH = (w - KEY_DISTANCE*(1 + arrKey[0].length))/arrKey[0].length;
		KEY_HEIGHT = (h - KEY_DISTANCE*(1 + arrKey.length + 1))/(arrKey.length+1);
		if(style <= 1) KEY_WIDTH++;
		rw = arrKey[0].length*KEY_WIDTH + KEY_DISTANCE*(arrKey[0].length) + 1;
		rh = (arrKey.length+1)*KEY_HEIGHT + KEY_DISTANCE*(arrKey.length + 1) + 1;

		//System.out.println("KEY_HEIGHT="+KEY_HEIGHT + " rh="+rh);
		//System.out.println("W="+arrKey[0].length + " H="+arrKey.length + " isUpperCase="+isUpperCase);
		
		if(style != 1 && style != 3)
			arrKey[arrKey.length - 1][arrKey[0].length - 1] = isUpperCase ? "ab" : "AB";
		if(style >= 2)
			arrKey[arrKey.length - 1][arrKey[0].length - 2] = style == 3 ? "Abc" : "123";
		if(img_buffKeyBoard == null) return;
		
		gg.setColor(0xFFFFFF);
		gg.fillRect(0, 0, w+1, h+1);
		for(int j = 0; j < arrKey.length; j++)
			for(int i = 0; i < arrKey[0].length; i++){
				if(style != 1 && style != 3){
					if(arrKey[j][i].length() > 0 && (j != arrKey.length - 1 && i != arrKey[0].length - 1) && !(style==2 && arrKey[j][i].charAt(0) == 'C'))
						arrKey[j][i] = isUpperCase ? arrKey[j][i].toUpperCase() : arrKey[j][i].toLowerCase();
				}
				draw_Key(gg, j, i, 0, 0, false);
			}
		
		drawCommand();
	}
	
	private void drawCommand(){
		if(gg==null)
			return;
		gg.setColor(0xFFFFFF);
		gg.fillRect(0, KEY_DISTANCE + arrKey.length*(KEY_HEIGHT + KEY_DISTANCE)-2, rw, KEY_HEIGHT+2);
		if(eRSK != null)
			for(int i = 0; i < 3; i++)
				draw_Key(gg, i, 0, 0, false);
		else 
			drawKey(gg, KEY_DISTANCE-2, KEY_DISTANCE + arrKey.length*(KEY_HEIGHT + KEY_DISTANCE)-2, rw-3, KEY_HEIGHT+1, 1, COLOR[COLOR_THEME][0],COLOR[COLOR_THEME][1],COLOR[COLOR_THEME][2]);
	}
	
	int COLOR[][] = {
			//  Above, Below, Border, Text
			{0xd7d7d7,0xc3c3c3,0xcecece,0x0},
			{0xa0dbf2,0x55bbe5,0x2ea5d5,0x0},
			{0xa5abff,0x5c65ff,0x3640e9,0x0},
			{0xe7adf4,0xd36ce9,0xb83bd3,0x0},
			{0xffe0a2,0xffd38b,0xffc672,0x0},
			{0xa0f2cc,0x55e5a3,0x27ba76,0x0},
			{0xd4ffd4,0xb2feb2,0x00cc00,0x0}
			};
	int COLOR_THEME = 0;
	int COLOR_SELECT = 2;
	private void draw_Key(Graphics g , int row, int col, int x, int y, boolean isPress){
		int xx = x + KEY_DISTANCE + col*(KEY_WIDTH + KEY_DISTANCE);
		int yy = y + KEY_DISTANCE + row*(KEY_HEIGHT + KEY_DISTANCE);
		
		if(isPress){
			if(arrKey[row][col].length() != 0)
				drawKey(g, xx-3-2, yy-KEY_HEIGHT-2, KEY_WIDTH+6+1, 2*KEY_HEIGHT+1, 1, COLOR[COLOR_SELECT][0],COLOR[COLOR_SELECT][1],COLOR[COLOR_SELECT][2]);
			else
				drawKey(g, xx-2, yy-2, KEY_WIDTH+1, KEY_HEIGHT+1, 1, COLOR[COLOR_SELECT][0],COLOR[COLOR_SELECT][1],COLOR[COLOR_SELECT][2]);
			RGBFont.fbold.drawString(g, arrKey[row][col],
					xx + KEY_WIDTH/2,
					yy - KEY_HEIGHT + (KEY_HEIGHT-RGBFont.fnormal.getHeight())/2 + 1, 2, COLOR[COLOR_SELECT][3]);
		} else {
			drawKey(g, xx-2, yy-2, KEY_WIDTH+1, KEY_HEIGHT+1, 1, COLOR[COLOR_THEME][0],COLOR[COLOR_THEME][1],COLOR[COLOR_THEME][2]);
			RGBFont.fnormal.drawString(g, arrKey[row][col],
					xx + KEY_WIDTH/2,
					yy + (KEY_HEIGHT-RGBFont.fnormal.getHeight())/2, 2, COLOR[COLOR_THEME][3]);
		}
	}
	private void draw_Key(Graphics g, int index, int x, int y, boolean isPress){
		// 0 1 2
		// 0 1 3
		int xx = x + KEY_DISTANCE + (index<2 ? index : 3)*(rw>>2);
		int yy = y + KEY_DISTANCE + arrKey.length*(KEY_HEIGHT + KEY_DISTANCE);
		int c = isPress ? COLOR_SELECT : COLOR_THEME;
		int w = (index==1 ? rw>>1 : rw>>2);
		drawKey(g, xx-2, yy-2, w -3, KEY_HEIGHT+1, 1, COLOR[c][0],COLOR[c][1],COLOR[c][2]);
		if(imgSK[index] != null)
			g.drawImage(imgSK[index], xx + (w>>1) - 2, yy + (KEY_HEIGHT>>1), Graphics.HCENTER|Graphics.VCENTER);
		else
			RGBFont.fbold.drawString(g, sSK[index], xx + (w>>1) - 2, yy + (KEY_HEIGHT-RGBFont.fnormal.getHeight())/2, 2, isPress ? 0x0000FF :0x888888);
	}
	
	private void drawKey(Graphics g, int x, int y, int w, int h, int acrConner, int colorAbove, int colorBelow, int colorBorder){
		//Fill
		g.setColor(colorBelow);
		g.fillRect(x + 2, y+2, w - 3, h-3);
		g.setColor(colorAbove);
		g.fillRect(x + 2, y+2, w - 3, (h>>1)-2);
		//border
		g.setColor(colorBorder);
	    w += 1;
	    h += 1;
	    g.fillRect(x + 2, y, w - 4, 1);
	    g.fillRect(x + 2, y + h - 1, w - 4, 1);
	    g.fillRect(x, y + 2, 1, h - 4);
	    g.fillRect(x + w - 1, y + 2, 1, h - 4);
	    g.fillRect(x + 1, y + 1, 1, 1);
	    g.fillRect(x + 1, y + h - 2, 1, 1);
	    g.fillRect(x + w - 2, y + 1, 1, 1);
	    g.fillRect(x + w - 2, y + h - 2, 1, 1);
	}
	
	public boolean changeMode(int inewMode){ // 0: abc 1: ABC 2: 123
		if(inewMode == 2){
			if(style == 2){
				style = 3;
				make_BaseKeyBoard();
				return true;
			}
		} else {
			if(style == 3) style = 2;
			
			isUpperCase = inewMode == 1;
			
			if(!(style == 1)){
				make_BaseKeyBoard();
				return true;
			}
		}
		return false;
	}
	
	private int passKEY(int row, int col){
		
		if(row == arrKey.length - 1 && col == 0){ // extent Key
			if(TextInput.me != null && TextInput.me.isTypeNumeric)
				return -43;
			style++;
			if(style>=3){
				if(style == 4 && TextInput.me != null)
					TextInput.me.inChangeMode(isUpperCase ? 1 : 0);
				style = 0;
			}
			
			make_BaseKeyBoard();
			System.out.println("Extent KeyBoard!");
			return -43;
		}
		
		if(arrKey[row][col]=="")
			return -43;
		
		if(style != 1 && style != 3 && row == arrKey.length - 1 && col == arrKey[0].length - 1){ // Change Mode
			changeMode(!isUpperCase ? 1 : 0);
			if(TextInput.me != null) TextInput.me.inChangeMode(isUpperCase ? 1 : 0);
			return -43;
		}
		
		if(style >= 2){ // Number
			if(arrKey[row][col].charAt(0) == 'C'){
				return 8; // # KEY.CLEAR
			} if(arrKey[row][col].equals(">>")){
				return -4;
			} if(arrKey[row][col].equals("<<")){
				return -3;
			} if(row == arrKey.length - 1 && col == arrKey[0].length - 2){
				System.out.println("Extent KeyBoard 123-ABC!");
				if(TextInput.me != null && TextInput.me.isTypeNumeric)
					return -43;
				changeMode(style == 2 ? 2 : isUpperCase ? 1 : 0);
				if(TextInput.me != null) TextInput.me.inChangeMode(style == 3 ? 2 : isUpperCase ? 1 : 0);
				return -43;
			}
		} else {
			if(row == arrKey.length - 2 && col == arrKey[0].length - 1){ // Clear
				return 8; // # KEY.CLEAR
			}
//			if(row == arrKey.length - 1 && col == arrKey[0].length - 2){ // Space
//				return 32;
//			}
		}
		return arrKey[row][col].charAt(0);
	}
	
	/* Get Width & get Height */
	public int getWidth(){ return rw;}
	public int getHeight(){ return rh;}
}
